//=======================================================
//  LVDS Data Output Interface 
//=======================================================
module lvds_3v1_output(
	// Internal Control Signals //
	 input               		fclka
	,input               		fclkb
	,input               		vclk
    ,input                      reset_n
    ,input      [11 -1: 0]      weight_in  //2047>1920
    ,input      [11 -1: 0]      height_in  //2047>1080
    ,input                      lvds1_vs_pulse
    ,input                      lvds2_vs_pulse
    // From lvds_input module
    ,input                      switch1_req
    ,output                     switch1_ack
    ,input                      switch2_req
    ,output                     switch2_ack
    // RGB RAM Interface
    ,output     [11 -1: 0]      lvds1_raddr
    ,input      [48 -1: 0]      lvds1_rdata
    ,output     [11 -1: 0]      lvds2_raddr
    ,input      [48 -1: 0]      lvds2_rdata
    // Bicubic output Interface
    ,output                     lvds1_read_valid
    ,output     [48 -1: 0]      lvds1_rdata_out
    ,output                     lvds2_read_valid
    ,output     [48 -1: 0]      lvds2_rdata_out
    // Display Configure Parameter
    ,input      [11 -1: 0]      SCAL_HS_PRELOGE
    ,input      [11 -1: 0]      SCAL_HS_PULSE  
    ,input      [11 -1: 0]      SCAL_HS_EPILOGE
    ,input      [11 -1: 0]      SCAL_HS_ACTIVE 
    ,input      [12 -1: 0]      SCAL_HS_TOTAL
    ,input      [11 -1: 0]      SCAL_VS_PRELOGE
    ,input      [11 -1: 0]      SCAL_VS_PULSE
    ,input      [11 -1: 0]      SCAL_VS_EPILOGE
    ,input      [11 -1: 0]      SCAL_VS_ACTIVE
    ,input      [12 -1: 0]      SCAL_VS_TOTAL
    // LVDS Output
    ,output                     TCLK1_Aout
    ,output                     TA1_Aout
    ,output                     TB1_Aout
    ,output                     TC1_Aout
    ,output                     TD1_Aout
    ,output                     TCLK1_Bout
    ,output                     TA1_Bout
    ,output                     TB1_Bout
    ,output                     TC1_Bout
    ,output                     TD1_Bout

    ,output                     TCLK2_Aout
    ,output                     TA2_Aout
    ,output                     TB2_Aout
    ,output                     TC2_Aout
    ,output                     TD2_Aout
    ,output                     TCLK2_Bout
    ,output                     TA2_Bout
    ,output                     TB2_Bout
    ,output                     TC2_Bout
    ,output                     TD2_Bout
	,output sclkb   //for test
);

//=======================================================
//  REG/WIRE declarations
//=======================================================
wire    [8 -1: 0]       pr1_da;
wire    [8 -1: 0]       pg1_da;
wire    [8 -1: 0]       pb1_da;
wire    [8 -1: 0]       pr1_db;
wire    [8 -1: 0]       pg1_db;
wire    [8 -1: 0]       pb1_db;
wire    [8 -1: 0]       pr2_da;
wire    [8 -1: 0]       pg2_da;
wire    [8 -1: 0]       pb2_da;
wire    [8 -1: 0]       pr2_db;
wire    [8 -1: 0]       pg2_db;
wire    [8 -1: 0]       pb2_db;

wire    [7 -1: 0]       TA_1Ain;
wire    [7 -1: 0]       TB_1Ain;
wire    [7 -1: 0]       TC_1Ain;
wire    [7 -1: 0]       TD_1Ain;
wire    [7 -1: 0]       TA_1Bin;
wire    [7 -1: 0]       TB_1Bin;
wire    [7 -1: 0]       TC_1Bin;
wire    [7 -1: 0]       TD_1Bin;
wire    [7 -1: 0]       TA_1Ain_buf;
wire    [7 -1: 0]       TB_1Ain_buf;
wire    [7 -1: 0]       TC_1Ain_buf;
wire    [7 -1: 0]       TD_1Ain_buf;
wire    [7 -1: 0]       TA_1Bin_buf;
wire    [7 -1: 0]       TB_1Bin_buf;
wire    [7 -1: 0]       TC_1Bin_buf;
wire    [7 -1: 0]       TD_1Bin_buf;

wire    [7 -1: 0]       TA_2Ain;
wire    [7 -1: 0]       TB_2Ain;
wire    [7 -1: 0]       TC_2Ain;
wire    [7 -1: 0]       TD_2Ain;
wire    [7 -1: 0]       TA_2Bin;
wire    [7 -1: 0]       TB_2Bin;
wire    [7 -1: 0]       TC_2Bin;
wire    [7 -1: 0]       TD_2Bin;
wire    [7 -1: 0]       TA_2Ain_buf;
wire    [7 -1: 0]       TB_2Ain_buf;
wire    [7 -1: 0]       TC_2Ain_buf;
wire    [7 -1: 0]       TD_2Ain_buf;
wire    [7 -1: 0]       TA_2Bin_buf;
wire    [7 -1: 0]       TB_2Bin_buf;
wire    [7 -1: 0]       TC_2Bin_buf;
wire    [7 -1: 0]       TD_2Bin_buf;

wire sclka;
wire sclkb;
wire ae_1a;
wire ae_1b;
wire ae_2a;
wire ae_2b;

//=======================================================
//  Module Instanse
//=======================================================
lvds_fetch U1_lvds_fetch (
	 .vclk(vclk)
    ,.reset_n(reset_n)
    ,.weight_in(weight_in)
    ,.height_in(height_in)
    ,.lvds_vs_pulse(lvds1_vs_pulse)
    ,.switch_req(switch1_req)
    ,.switch_ack(switch1_ack)
    ,.lvds_raddr(lvds1_raddr)
    ,.lvds_rdata(lvds1_rdata)
    ,.lvds_read_valid(lvds1_read_valid)
    ,.lvds_rdata_out(lvds1_rdata_out)

    ,.SCAL_HS_PRELOGE(SCAL_HS_PRELOGE)
    ,.SCAL_HS_PULSE(SCAL_HS_PULSE)  
    ,.SCAL_HS_EPILOGE(SCAL_HS_EPILOGE)
    ,.SCAL_HS_ACTIVE(SCAL_HS_ACTIVE) 
    ,.SCAL_HS_TOTAL(SCAL_HS_TOTAL)
    ,.SCAL_VS_PRELOGE(SCAL_VS_PRELOGE)
    ,.SCAL_VS_PULSE(SCAL_VS_PULSE)
    ,.SCAL_VS_EPILOGE(SCAL_VS_EPILOGE)
    ,.SCAL_VS_ACTIVE(SCAL_VS_ACTIVE)
    ,.SCAL_VS_TOTAL(SCAL_VS_TOTAL)

    ,.pr_db(pr1_db) 
    ,.pg_db(pg1_db) 
    ,.pb_db(pb1_db) 
    ,.pr_da(pr1_da) 
    ,.pg_da(pg1_da) 
    ,.pb_da(pb1_da) 
    ,.de(de1)
    ,.hs(hs1)
    ,.vs(vs1)
);

lvds_fetch U2_lvds_fetch (
	 .vclk(vclk)
    ,.reset_n(reset_n)
    ,.weight_in(weight_in)
    ,.height_in(height_in)
    ,.lvds_vs_pulse(lvds2_vs_pulse)
    ,.switch_req(switch2_req)
    ,.switch_ack(switch2_ack)
    ,.lvds_raddr(lvds2_raddr)
    ,.lvds_rdata(lvds2_rdata)
    ,.lvds_read_valid(lvds2_read_valid)
    ,.lvds_rdata_out(lvds2_rdata_out)

    ,.SCAL_HS_PRELOGE(SCAL_HS_PRELOGE)
    ,.SCAL_HS_PULSE(SCAL_HS_PULSE)  
    ,.SCAL_HS_EPILOGE(SCAL_HS_EPILOGE)
    ,.SCAL_HS_ACTIVE(SCAL_HS_ACTIVE) 
    ,.SCAL_HS_TOTAL(SCAL_HS_TOTAL)
    ,.SCAL_VS_PRELOGE(SCAL_VS_PRELOGE)
    ,.SCAL_VS_PULSE(SCAL_VS_PULSE)
    ,.SCAL_VS_EPILOGE(SCAL_VS_EPILOGE)
    ,.SCAL_VS_ACTIVE(SCAL_VS_ACTIVE)
    ,.SCAL_VS_TOTAL(SCAL_VS_TOTAL)

    ,.pr_db(pr2_db) 
    ,.pg_db(pg2_db) 
    ,.pb_db(pb2_db) 
    ,.pr_da(pr2_da) 
    ,.pg_da(pg2_da) 
    ,.pb_da(pb2_da) 
    ,.de(de2)
    ,.hs(hs2)
    ,.vs(vs2)
);

//=======================================================
//  Structural coding
//=======================================================
assign RST_Tx = !reset_n;
assign TA_1Ain = {pg1_da[2], pr1_da[7:2]};
assign TB_1Ain = {pb1_da[3:2], pg1_da[7:3]};
assign TC_1Ain = {de1, vs1, hs1, pb1_da[7:4]};
assign TD_1Ain = {1'b1, pb1_da[1:0], pg1_da[1:0], pr1_da[1:0]};
assign TA_1Bin = {pg1_db[2], pr1_db[7:2]};
assign TB_1Bin = {pb1_db[3:2], pg1_db[7:3]};
assign TC_1Bin = {de1, vs1, hs1, pb1_db[7:4]};
assign TD_1Bin = {1'b1, pb1_db[1:0], pg1_db[1:0], pr1_db[1:0]};

assign TA_2Ain = {pg2_da[2], pr2_da[7:2]};
assign TB_2Ain = {pb2_da[3:2], pg2_da[7:3]};
assign TC_2Ain = {de2, vs2, hs2, 4'b1111};//pb2_da[7:4]};
assign TD_2Ain = 7'b0111111; //{1'b1, pb2_da[1:0], pg2_da[1:0], pr2_da[1:0]};
assign TA_2Bin = {pg2_db[2], pr2_db[7:2]};
assign TB_2Bin = {pb2_db[3:2], pg2_db[7:3]};
assign TC_2Bin = {de2, !vs2, !hs2, pb2_db[7:4]};
assign TD_2Bin = {1'b1, pb2_db[1:0], pg2_db[1:0], pr2_db[1:0]};

reg    stop1, stop2, stop3, stop;        // pipe delay
//--------------------------------------------------------------------
//-- divider sync signal generation
//--------------------------------------------------------------------
//always @(posedge fclka or negedge reset_n)
always @(posedge vclk or negedge reset_n)
begin
   if (!reset_n) begin
      stop1    <= 1'b1;
      stop2    <= 1'b1;
      stop3    <= 1'b1;
      stop     <= 1'b1;
   end else begin
      stop1    <= 1'b0;
      stop2    <= stop1;
      stop3    <= stop2;
      stop     <= stop3;
   end
end

fifo_28b fifo1a(.Data    ({TA_1Ain,TB_1Ain,TC_1Ain,TD_1Ain}), 
               .WrClock (vclk), 
               .RdClock (sclka), 
               .WrEn    (1'b1), 
               .RdEn    (~ae_1a), 
               .Reset   (RST_Tx), 
               .RPReset (RST_Tx), 
               .Q       ({TA_1Ain_buf,TB_1Ain_buf,TC_1Ain_buf,TD_1Ain_buf}),  
               .Empty   (), 
               .Full    (), 
               .AlmostEmpty (ae_1a), 
               .AlmostFull ());
    
LVDS_7_to_1_TX U_LVDS_7to1_TXA (
       .RST_Tx(RST_Tx)

      ,.T0_in(TA_1Ain_buf)
      ,.T1_in(TB_1Ain_buf)
      ,.T2_in(TC_1Ain_buf)
      ,.T3_in(TD_1Ain_buf)

      ,.eclk(fclka)
      ,.clk_s(vclk)
      ,.stop(stop)
      ,.sclk(sclka)
      ,.TCLK_out(TCLK1_Aout)
      ,.T0_out(TA1_Aout)
      ,.T1_out(TB1_Aout)
      ,.T2_out(TC1_Aout)
      ,.T3_out(TD1_Aout)
);

fifo_28b fifo1b(.Data    ({TA_1Bin,TB_1Bin,TC_1Bin,TD_1Bin}), 
               .WrClock (vclk), 
               .RdClock (sclkb), 
               .WrEn    (1'b1), 
               .RdEn    (~ae_1b), 
               .Reset   (RST_Tx), 
               .RPReset (RST_Tx), 
               .Q       ({TA_1Bin_buf,TB_1Bin_buf,TC_1Bin_buf,TD_1Bin_buf}),  
               .Empty   (), 
               .Full    (), 
               .AlmostEmpty (ae_1b), 
               .AlmostFull ());

fifo_28b fifo2a(.Data    ({TA_2Ain,TB_2Ain,TC_2Ain,TD_2Ain}), 
               .WrClock (vclk), 
               .RdClock (sclkb), 
               .WrEn    (1'b1), 
               .RdEn    (~ae_2a), 
               .Reset   (RST_Tx), 
               .RPReset (RST_Tx), 
               .Q       ({TA_2Ain_buf,TB_2Ain_buf,TC_2Ain_buf,TD_2Ain_buf}),  
               .Empty   (), 
               .Full    (), 
               .AlmostEmpty (ae_2a), 
               .AlmostFull ());
    
fifo_28b fifo2b(.Data    ({TA_2Bin,TB_2Bin,TC_2Bin,TD_2Bin}), 
               .WrClock (vclk), 
               .RdClock (sclkb), 
               .WrEn    (1'b1), 
               .RdEn    (~ae_2b), 
               .Reset   (RST_Tx), 
               .RPReset (RST_Tx), 
               .Q       ({TA_2Bin_buf,TB_2Bin_buf,TC_2Bin_buf,TD_2Bin_buf}),  
               .Empty   (), 
               .Full    (), 
               .AlmostEmpty (ae_2b), 
               .AlmostFull ());
               
LVDS_7_to_1_TX_12Lane U_LVDS_7to1_inst
     (
      .RST_Tx(RST_Tx)  ,
              
      .OLED1_T0_in(TA_1Bin_buf),
      .OLED1_T1_in(TB_1Bin_buf),
      .OLED1_T2_in(TC_1Bin_buf),
      .OLED1_T3_in(TD_1Bin_buf),
	  .OLED2_T0_in(TA_2Ain_buf),
      .OLED2_T1_in(TB_2Ain_buf),
      .OLED2_T2_in(TC_2Ain_buf),
      .OLED2_T3_in(TD_2Ain_buf),
      .OLED2_T4_in(TA_2Bin_buf),
      .OLED2_T5_in(TB_2Bin_buf),
      .OLED2_T6_in(TC_2Bin_buf),
      .OLED2_T7_in(TD_2Bin_buf),        
      .eclk(fclkb),
      .clk_s(vclk),
      .stop(stop),
      .sclk(sclkb),
      .TCLK_out1(TCLK1_Bout),
	  .TCLK_out2(TCLK2_Aout),
	  .TCLK_out3(TCLK2_Bout),
      .OLED1_T0_out(TA1_Bout),
      .OLED1_T1_out(TB1_Bout),
      .OLED1_T2_out(TC1_Bout),
      .OLED1_T3_out(TD1_Bout),
	  .OLED2_T0_out(TA2_Aout),
      .OLED2_T1_out(TB2_Aout),
      .OLED2_T2_out(TC2_Aout),
      .OLED2_T3_out(TD2_Aout),
	  .OLED2_T4_out(TA2_Bout),
      .OLED2_T5_out(TB2_Bout),
      .OLED2_T6_out(TC2_Bout),
      .OLED2_T7_out(TD2_Bout)   
    );
	
endmodule

